home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Programming / MuManual / C_Sources / MuSetCacheMode.c < prev    next >
C/C++ Source or Header  |  1999-11-28  |  22KB  |  470 lines

  1. /*****************************************************************
  2.  ** MuSetCacheMode                                              **
  3.  **                                                             **
  4.  ** Reprogram MMU tables selectively.                           **
  5.  ** Release 40.7, © 1999 THOR-Software inc.                     **
  6.  ** 28.11.1999 Thomas Richter                                   **
  7.  *****************************************************************/
  8.  
  9. /// Includes
  10. #include <exec/types.h>
  11. #include <exec/memory.h>
  12. #include <exec/ports.h>
  13. #include <dos/dos.h>
  14. #include <mmu/mmubase.h>
  15. #include <mmu/context.h>
  16. #include <mmu/mmutags.h>
  17. #include <workbench/startup.h>
  18.  
  19. #include <thor/conversions.h>
  20.  
  21. #include <proto/exec.h>
  22. #include <proto/mmu.h>
  23. #include <proto/dos.h>
  24. #include <proto/icon.h>
  25. #include <string.h>
  26. ///
  27. /// Defines
  28. #define STRINGDATE "28.11.99"
  29. #define STRINGVERSION "40.7"
  30. #define TEMPLATE "ADDRESS=FROM/A,SIZE/A,COPYBACK/S,WRITETHROUGH/S,NOCACHESERIALIZED=CACHEINHIBIT/S,NONSERIAL/S,NOCACHE=IMPRECISE/S,VALID/S,INVALID/S,BLANK/S,IO=IOSPACE/S,NOIO=NOIOSPACE/S,ROM/S,NOROM/S,WRITEPROTECTED/S,NOTWRITEPROTECTED/S,USERONLY/S,SUPERVISORONLY/S,VERBOSE/S"
  31. #define CACHEFLAGS (MAPP_CACHEINHIBIT|MAPP_NONSERIALIZED|MAPP_IMPRECISE|MAPP_COPYBACK)
  32. #define ROMFLAGS (MAPP_ROM|MAPP_WRITEPROTECTED)
  33.  
  34. #define OPT_ADDRESS 0
  35. #define OPT_SIZE 1
  36. #define OPT_COPYBACK 2
  37. #define OPT_WRITETHROUGH 3
  38. #define OPT_NOCACHE 4
  39. #define OPT_NOCACHESERIALIZED 5
  40. #define OPT_NOCACHEIMPRECISE 6
  41. #define OPT_VALID 7
  42. #define OPT_INVALID 8
  43. #define OPT_BLANK 9
  44. #define OPT_IO 10
  45. #define OPT_NOIO 11
  46. #define OPT_ROM 12
  47. #define OPT_NOROM 13
  48. #define OPT_WRITEPROTECTED 14
  49. #define OPT_NOTWRITEPROTECTED 15
  50. #define OPT_USERONLY 16
  51. #define OPT_SUPERVISORONLY 17
  52. #define OPT_VERBOSE 18
  53. #define OPT_WINDOW 19
  54. #define OPT_COUNT 20
  55.  
  56. #define WHICH_ALL       3
  57. #define WHICH_USER      1
  58. #define WHICH_SUPER     2
  59. ///
  60. /// Statics
  61. struct MMUBase *MMUBase;
  62. struct DosLibrary *DOSBase;
  63. struct ExecBase *SysBase;
  64. struct Library *IconBase;
  65. ///
  66. /// Protos
  67. int __asm __saveds main(void);
  68. int SetCacheMode(ULONG from,ULONG size,ULONG flags,ULONG mask,ULONG which);
  69. struct RDArgs *ReadTTArgs(struct WBStartup *msg,LONG args[],struct RDArgs **tmp);
  70. ///
  71.  
  72. char version[]="$VER: MuSetCacheMode " STRINGVERSION " (" STRINGDATE ") © THOR";
  73.  
  74. /// main
  75. int __asm __saveds main(void)
  76. {
  77. LONG args[OPT_COUNT];
  78. struct RDArgs *rd,*myrd;
  79. struct Process *proc;
  80. int rc=20;
  81. LONG err;
  82. struct WBStartup *msg;
  83. BPTR oldout;
  84. struct MsgPort *oldconsole;
  85. LONG flags,which;
  86. char *whichmsg;
  87. int from=0,size=0;
  88. ULONG mask;
  89. char flagsmsg[256];
  90.  
  91.  
  92.         SysBase=*((struct ExecBase **)(4L));
  93.  
  94.         memset(args,0,sizeof(LONG)*OPT_COUNT);
  95.         flagsmsg[0]='\0';                       /* Clear this string */
  96.  
  97.         /* Wait for the workbench startup, if any */
  98.         proc=(struct Process *)FindTask(NULL);
  99.  
  100.         if (!(proc->pr_CLI)) {
  101.                 WaitPort(&(proc->pr_MsgPort));
  102.                 msg=(struct WBStartup *)GetMsg(&(proc->pr_MsgPort));
  103.         } else  msg=NULL;
  104.  
  105.         if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) {
  106.                 if (MMUBase=(struct MMUBase *)OpenLibrary("mmu.library",41L)) {
  107.  
  108.                         err=ERROR_REQUIRED_ARG_MISSING;
  109.  
  110.                         myrd=NULL;      /* reset the temporary ReadArgs */
  111.                         oldout=NULL;
  112.                         oldconsole=NULL;
  113.                         if (msg) {
  114.                                 oldout=SelectOutput(NULL);
  115.                                 oldconsole=SetConsoleTask(NULL);
  116.                                 rd=ReadTTArgs(msg,args,&myrd);
  117.                         } else  rd=ReadArgs(TEMPLATE,args,NULL);
  118.  
  119.                         if (rd) {
  120.                                 if (!GetMMUType()) {
  121.                                         Printf("MuSetCacheMode requires a working MMU.\n");
  122.                                         err=10;
  123.                                 } else {
  124.  
  125.                                         err=0;
  126.  
  127.                                         if (args[OPT_ADDRESS]==NULL || args[OPT_SIZE]==NULL)
  128.                                                 err=ERROR_REQUIRED_ARG_MISSING;
  129.  
  130.                                         if (err==0) {
  131.  
  132.                                                 if (!StrToL((char *)(args[OPT_ADDRESS]),NULL,&from,16))
  133.                                                         err=ERROR_BAD_NUMBER;
  134.  
  135.                                                 if (!StrToL((char *)(args[OPT_SIZE]),NULL,&size,16)) {
  136.                                                         err=ERROR_BAD_NUMBER;
  137.                                                 } else if (size==0) err=ERROR_BAD_NUMBER;
  138.  
  139.  
  140.                                         }       
  141.                                         if (err==0) {
  142.  
  143.                                                 flags=0;
  144.                                                 mask=0;
  145.  
  146.                                                 if (args[OPT_VALID]) {
  147.                                                         mask |= MAPP_INVALID | MAPP_BLANK | MAPP_REPAIRABLE;
  148.                                                         strcat(flagsmsg,"valid ");
  149.                                                 }
  150.                                                 if (args[OPT_IO]) {
  151.                                                         flags &= ~CACHEFLAGS;
  152.                                                         flags |= MAPP_IO|MAPP_CACHEINHIBIT;
  153.                                                         mask |= MAPP_IO|CACHEFLAGS;
  154.                                                         strcat(flagsmsg,"IO space ");
  155.                                                 }
  156.                                                 if (args[OPT_NOIO]) {
  157.                                                         mask |= MAPP_IO;
  158.                                                         flags &= ~MAPP_IO;
  159.                                                         strcat(flagsmsg,"memory space ");
  160.                                                 }
  161.                                                 if (args[OPT_COPYBACK]) {
  162.                                                         flags &= ~CACHEFLAGS;
  163.                                                         flags |= MAPP_COPYBACK;
  164.                                                         mask |= CACHEFLAGS;
  165.                                                         strcat(flagsmsg,"copyback ");
  166.                                                 }
  167.                                                 if (args[OPT_WRITETHROUGH]) {
  168.                                                         flags &= ~CACHEFLAGS;    /* writethrough is the default */
  169.                                                         mask |= CACHEFLAGS;
  170.                                                         strcat(flagsmsg,"writethrough ");
  171.                                                 }
  172.                                                 if (args[OPT_NOCACHE]) {
  173.                                                         flags &= ~CACHEFLAGS;
  174.                                                         flags |= MAPP_CACHEINHIBIT;
  175.                                                         mask |= CACHEFLAGS;
  176.                                                         strcat(flagsmsg,"cacheinhibit ");
  177.                                                 }
  178.                                                 if (args[OPT_NOCACHESERIALIZED]) {
  179.                                                         flags &= ~CACHEFLAGS;
  180.                                                         flags |= MAPP_CACHEINHIBIT | MAPP_NONSERIALIZED;
  181.                                                         mask |= CACHEFLAGS;
  182.                                                         if (!args[OPT_NOCACHEIMPRECISE]) {
  183.                                                                 strcat(flagsmsg,"cacheinhibit non-serialized ");
  184.                                                         }
  185.                                                 }
  186.                                                 if (args[OPT_NOCACHEIMPRECISE]) {
  187.                                                         flags &= ~CACHEFLAGS;
  188.                                                         flags |= MAPP_CACHEINHIBIT | MAPP_IMPRECISE;
  189.                                                         mask |= CACHEFLAGS;
  190.                                                         strcat(flagsmsg,"cacheinhibit imprecise ");
  191.                                                         if (args[OPT_NOCACHESERIALIZED]) {
  192.                                                                 flags |= MAPP_NONSERIALIZED;
  193.                                                                 strcat(flagsmsg,"non-serialized ");
  194.                                                         }
  195.                                                 }
  196.                                                 if (args[OPT_ROM]) {
  197.                                                         flags &= ~ROMFLAGS;
  198.                                                         flags |= MAPP_ROM;
  199.                                                         mask |= ROMFLAGS;
  200.                                                         strcat(flagsmsg,"ROM ");
  201.                                                 }
  202.                                                 if (args[OPT_NOROM]) {
  203.                                                         mask |= MAPP_ROM;
  204.                                                         flags &= ~MAPP_ROM;
  205.                                                         strcat(flagsmsg,"no ROM ");
  206.                                                 }
  207.                                                 if (args[OPT_WRITEPROTECTED]) {
  208.                                                         flags &= ~ROMFLAGS;
  209.                                                         flags |= MAPP_WRITEPROTECTED;
  210.                                                         mask |= ROMFLAGS;
  211.                                                         strcat(flagsmsg,"read only ");
  212.                                                 }
  213.                                                 if (args[OPT_NOTWRITEPROTECTED]) {
  214.                                                         mask |= MAPP_WRITEPROTECTED;
  215.                                                         flags &= ~MAPP_WRITEPROTECTED;
  216.                                                         strcat(flagsmsg,"read/write ");
  217.                                                 }
  218.                                                 if (args[OPT_INVALID]) {
  219.                                                         mask = 0xffffffff;
  220.                                                         flags = MAPP_INVALID | MAPP_REPAIRABLE;
  221.                                                         strcpy(flagsmsg,"invalid ");
  222.                                                 }
  223.                                                 if (args[OPT_BLANK]) {
  224.                                                         mask = 0xffffffff;
  225.                                                         flags = MAPP_BLANK;
  226.                                                         strcpy(flagsmsg,"blank ");
  227.                                                 }
  228.                                                 which=WHICH_ALL;
  229.                                                 whichmsg = "user and supervisor";
  230.                                                 if (args[OPT_USERONLY]) {
  231.                                                         which = WHICH_USER;
  232.                                                         whichmsg = "user";
  233.                                                 }
  234.                                                 if (args[OPT_SUPERVISORONLY]) {
  235.                                                         which=WHICH_SUPER;
  236.                                                         whichmsg = "supervisor";
  237.                                                 }
  238.  
  239.                                                 if (flagsmsg[0]=='\0') {
  240.                                                         err=ERROR_REQUIRED_ARG_MISSING;
  241.                                                 } else {
  242.                                                         err=SetCacheMode((ULONG)from,(LONG)size,flags,mask,which);
  243.                                                         if ((err==0) && args[OPT_VERBOSE]) {
  244.                                                                 Printf("%s.\n"
  245.                                                                        "Set %s mode from 0x%lx, size 0x%lx to %s\n",
  246.                                                                        version+6,whichmsg,from,size,flagsmsg);
  247.                                                         }
  248.                                                 }
  249.                                         }
  250.                                 }
  251.  
  252.                                 FreeArgs(rd);
  253.                                 if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  254.                                 if (msg)  Close(SelectOutput(NULL));
  255.                         } else  err=IoErr();
  256.  
  257.                         if (msg) {
  258.                                 SelectOutput(oldout);
  259.                                 SetConsoleTask(oldconsole);
  260.                         }
  261.  
  262.                         if (err<64) {
  263.                                 rc=err;
  264.                                 err=0;
  265.                         } else {
  266.                                 if (!msg) PrintFault(err,"MuSetCacheMode failed");
  267.                                 rc=10;
  268.                         }
  269.                         SetIoErr(err);
  270.  
  271.                         CloseLibrary((struct Library *)MMUBase);
  272.                 } else if (!msg) PrintFault(ERROR_OBJECT_NOT_FOUND,"MuSetCacheMode requires the mmu.library V41 or better");
  273.                 CloseLibrary((struct Library *)DOSBase);
  274.         }
  275.  
  276.         if (msg) {
  277.                 Forbid();
  278.                 ReplyMsg((struct Message *)msg);
  279.         }
  280.         return rc;
  281. }
  282. ///
  283. /// ReadTTArgs
  284. struct RDArgs *ReadTTArgs(struct WBStartup *msg,LONG args[],struct RDArgs **tmp)
  285. {
  286. struct WBArg *wbarg;
  287. struct DiskObject *dop;
  288. char **tt;                      /* ToolTypes array */
  289. char *wbstr;                    /* Our self-made workbench argument string */
  290. char *here;
  291. BPTR oldlock;
  292. ULONG len;
  293. struct RDArgs *rd=NULL,*myrd=NULL;
  294. LONG err=0;
  295. BPTR newout;
  296.  
  297.         if (IconBase=OpenLibrary("icon.library",37L)) {
  298.                 if (wbarg=msg->sm_ArgList) {
  299.                         /* use a project icon if there is one... */
  300.                         if (msg->sm_NumArgs > 1) wbarg++;
  301.  
  302.                         /* go into the directory */
  303.                         oldlock=CurrentDir(wbarg->wa_Lock);
  304.  
  305.                         if (dop=GetDiskObject(wbarg->wa_Name)) {
  306.                                 if (tt=dop->do_ToolTypes) {
  307.                                         /* Read a special tool type for the output window */
  308.  
  309.                                         /* Calc the size of the argument string */
  310.  
  311.                                         len = 3;        /* reserve space for SPC,LF,NUL */
  312.                                         while (*tt) {
  313.                                                 len += strlen(*tt)+1;   /* string, plus space */
  314.                                                 tt++;
  315.                                         }
  316.  
  317.                                         if (wbstr=AllocVec(len,MEMF_PUBLIC)) {
  318.                                                 /* Now copy the arguments into this string, one by one
  319.                                                    and check whether the argument string is still valid. */
  320.  
  321.                                                 tt=dop->do_ToolTypes;
  322.                                                 here=wbstr;
  323.                                                 do{
  324.                                                         *here='\0';                     /* terminate string */
  325.                                                         /* Check whether this tool type is
  326.                                                            commented out. Just ignore it in this case */
  327.                                                         if (*tt) {
  328.                                                                 if (**tt=='(' || **tt==';')
  329.                                                                         continue;
  330.  
  331.                                                                 strcpy(here,*tt);      /* Add TT string */
  332.                                                         }
  333.                                                         len=strlen(here);
  334.                                                         here[len]='\n';
  335.                                                         here[len+1]='\0';               /* terminate string */
  336.  
  337.                                                         /* Now try to ReadArg' this string */
  338.  
  339.                                                         /* release old arguments left over from last loop */
  340.                                                         if (rd) FreeArgs(rd);
  341.                                                         if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  342.                                                         rd=NULL;
  343.                                                         memset(args,0,sizeof(LONG)*OPT_COUNT);
  344.  
  345.                                                         if (myrd=AllocDosObject(DOS_RDARGS,NULL)) {
  346.                                                                 /* Allocate and setup the ReadArgs source */
  347.                                                                 myrd->RDA_Source.CS_Buffer=wbstr;
  348.                                                                 myrd->RDA_Source.CS_Length=strlen(wbstr);
  349.  
  350.                                                                 if (rd=ReadArgs(TEMPLATE ",WINDOW/K",args,myrd)) {
  351.                                                                         /* Is this still valid? */
  352.                                                                         here[len]=' ';
  353.                                                                         here+=len+1;
  354.                                                                         /* if so, accept this argument and go on */
  355.                                                                 } else {
  356.                                                                         err=IoErr();
  357.                                                                         if (err==ERROR_NO_FREE_STORE) break;
  358.                                                                         else    err=0;  /* Ignore unknown or invalid arguments silently */
  359.                                                                 }
  360.                                                         } else {
  361.                                                                 err=ERROR_NO_FREE_STORE;
  362.                                                                 break;
  363.                                                         }
  364.                                                 }while(*tt++);
  365.  
  366.                                                 FreeVec(wbstr);
  367.                                         } else err=ERROR_NO_FREE_STORE;
  368.                                 } else err=ERROR_REQUIRED_ARG_MISSING; /* Huh, how should this happen ? */
  369.                                 FreeDiskObject(dop);
  370.                         } else err=IoErr();
  371.                         CurrentDir(oldlock);
  372.                 } else err=ERROR_REQUIRED_ARG_MISSING; /* This should not happen either */
  373.                 CloseLibrary(IconBase);
  374.         } else err=ERROR_OBJECT_NOT_FOUND;    /* This should not happen */
  375.  
  376.         /* Open an output stream */
  377.  
  378.         if (err==0) {
  379.                 if (newout=Open((args[OPT_WINDOW])?((char *)args[OPT_WINDOW]):("NIL:"),MODE_NEWFILE)) {
  380.                         SelectOutput(newout);
  381.                         /* Hack in the output console. Well, well... */
  382.                         SetConsoleTask(((struct FileHandle *)(BADDR(newout)))->fh_Type);
  383.                 } else err=IoErr();
  384.         }
  385.  
  386.         if (err) {
  387.                 if (rd)   FreeArgs(rd);
  388.                 if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  389.                 SetIoErr(err);
  390.                 rd=NULL;
  391.                 myrd=NULL;
  392.         }
  393.  
  394.         *tmp=myrd;
  395.         return rd;
  396. }
  397. ///
  398. /// SetCacheMode
  399. int SetCacheMode(ULONG from,ULONG size,ULONG flags,ULONG mask,ULONG which)
  400. {
  401. struct MMUContext *ctx,*sctx;   /* default context, supervisorcontext */
  402. struct MinList *ctxl,*sctxl;
  403. ULONG psize;
  404. int err;
  405.  
  406.         ctx=DefaultContext();   /* get the default context */
  407.         sctx=SuperContext(ctx); /* get the supervisor context for this one */
  408.  
  409.         psize=GetPageSize(ctx);
  410.         if (size & (psize-1)) {
  411.                 Printf("The given size 0x%lx is not divisible by the page size 0x%lx.\n",size,psize);
  412.                 return ERROR_BAD_NUMBER;
  413.         }
  414.         if (from & (psize-1)) {
  415.                 Printf("The given address 0x%lx is not divisible by the page size 0x%lx.\n",from,psize);
  416.                 return ERROR_BAD_NUMBER;
  417.         }
  418.         if (psize!=GetPageSize(sctx)) {
  419.                 Printf("MuSetCacheMode does not support different user and supervisor page sizes.\n");
  420.                 return ERROR_OBJECT_WRONG_TYPE;
  421.         }
  422.  
  423.         LockContextList();
  424.         LockMMUContext(ctx);
  425.         LockMMUContext(sctx);
  426.  
  427.         err=ERROR_NO_FREE_STORE;
  428.  
  429.         if (ctxl=GetMapping(ctx)) {
  430.          if (sctxl=GetMapping(sctx)) {
  431.  
  432.            err=0;
  433.  
  434.            if (which & WHICH_USER) {
  435.                 if (!SetProperties(ctx,flags,mask,from,size,TAG_DONE)) {
  436.                         err=ERROR_NO_FREE_STORE;
  437.                 }
  438.            }
  439.  
  440.            if (which & WHICH_SUPER) {
  441.                 if (!SetProperties(sctx,flags,mask,from,size,TAG_DONE)) {
  442.                         err=ERROR_NO_FREE_STORE;
  443.                 }
  444.            }
  445.  
  446.            if (err==0) {
  447.                 if (!RebuildTrees(ctx,sctx,NULL)) {
  448.                            err=ERROR_NO_FREE_STORE;
  449.                 }
  450.            }
  451.  
  452.            if (err) {
  453.                    SetPropertyList(ctx,ctxl);
  454.                    SetPropertyList(sctx,sctxl);
  455.            }
  456.  
  457.            ReleaseMapping(sctx,sctxl);
  458.          }
  459.          ReleaseMapping(ctx,ctxl);
  460.         }
  461.  
  462.         UnlockMMUContext(sctx);
  463.         UnlockMMUContext(ctx);
  464.         UnlockContextList();
  465.  
  466.         return err;
  467. }
  468. ///
  469.  
  470.